容器

我们可以将字符堆栈类型推广到一个任意类型的堆栈的类型,方法是将它做成一个模板(template),用一个模板参数取代特定的类型 char。例如,

    template<class T> class Stack
    {
        T* v;
        int max_size;
        int top;
    public:
        class Underflow { };
        class Overflow { };

        Stack(int s);    // 构造函数
        ~Stack();        // 析构函数

        void push(T);
        T pop();
    };

前缀 template <class T> 说明在以此作为前缀的声明中,T 将被看做是一个参数。

成员函数可以类似地定义为:

    template<class T> void Stack<T>::push(T c)
    {
        if(top == max_size) throw Overflow();
        v[top] = c;
        top = top + 1;
    }

    template<class T> T Stack<T>::pop()
    {
        if(top == 0) throw Underflow();
        top = top - 1;
        return v[top];
    }

有了这些定义之后,我们就可以按

    Stack<char> sc(200);         // 200个字符的堆栈
    Stack<complex> scplx(30);    // 30个复数的堆栈
    Stack<list<int>> sli(45);    // 45个整数表的堆栈

    void f()
    {
        sc.push('c');
        if(sc.pop() != 'c') throw Bad_pop();

        scplx.push(complex(1.2));
        if(scplx.pop() != complex(1.2)) throw Bad_pop();
    }

方式使用堆栈了。类似地,我们也能将表、向量、映射(也就是关联数组)等都定义为模板。一个能保存某种类型的一集元素的类,一般被称为一个容器类,或简单地称做容器。

模板是一种编译时的机制,因此,与“手工编写的代码”相比,它们的使用并不引起任何额外的运行时开销。

🔚